package com.chaodev.base.controller;

import com.alibaba.fastjson.JSONObject;
import com.chaodev.base.model.Result;
import com.chaodev.base.model.ResultEnum;
import com.chaodev.base.utils.Base64EnOut;
import com.chaodev.base.utils.QrCodeGenerate;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Paths;
import java.util.*;

import static com.chaodev.base.utils.Base64EnOut.Base64Decode;
import static com.chaodev.base.utils.Base64EnOut.Base64Encode;

/**
 * vcbase
 *
 * @author 95634
 * @描述
 * @date 2023/5/19 10:47
 **/
@Controller
@RequestMapping("attach")
@PropertySource("classpath:upload.properties")
public class UploadNewController {
    Logger LOGGER= LoggerFactory.getLogger(UploadNewController.class);
    @Resource
    Environment env;

    @ResponseBody
    @RequestMapping(value = "/uploadFile")
    public String uploadFile(@RequestParam(value = "upfile", required = false) MultipartFile file, HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        //获取文件的文件名字(后面要用到)
        String filename = file.getOriginalFilename();
        //这个url是要上传到另一个服务器上接口
        String url = String.format("http://10.124.13.37:8080/fileupload/attach/uploadFileNew");
        Object object = null;
        Base64EnOut base64EnOut = new Base64EnOut();
        String result = null;
        JSONObject map = null;
        //创建HttpClients实体类
        CloseableHttpClient aDefault = HttpClients.createDefault();
        try {
            HttpPost httpPost = new HttpPost(url);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            //这里就是自己踩的坑,需要使用file.getBytes()
            //builder.addBinaryBody("file",file.getInputStream(),ContentType.create("multipart/form-data"),filename);
            //使用这个，另一个服务就可以接收到这个file文件了
            //// System.out.print(filename);
            builder.addBinaryBody("file", file.getBytes(), ContentType.create("multipart/form-data"), filename).setCharset(CharsetUtils.get("UTF-8"));
            HttpEntity entity = builder.build();

            httpPost.setEntity(entity);
            ResponseHandler<Object> rh = new ResponseHandler<Object>() {
                @Override
                public Object handleResponse(HttpResponse response) throws IOException {
                    HttpEntity entity = response.getEntity();
                    String result = EntityUtils.toString(entity, "UTF-8");
                    return result;
                }
            };
            aDefault = HttpClients.createDefault();
            object = aDefault.execute(httpPost, rh);
            map = JSONObject.parseObject(object.toString());
        } catch (Exception e) {
            LOGGER.error(String.format(e.toString()));
            map.put("state", "上传失败");
        } finally {
            aDefault.close();
        }
        map.put("original", filename);
        return map.toJSONString();
    }

    @ResponseBody
    @RequestMapping(value = "/uploadAtt", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
    public Result uploadhostFile(@RequestParam(value = "file", required = false) MultipartFile[] file1,
                                 HttpServletRequest request) throws Exception {
//        Att att = new Att();

        //获取文件保存后面的动态路径
        String backPath = this.getPath();
        //服务器地址
        StringBuilder serverPath = new StringBuilder();

//        if(request.getServerName().contains("com")){
//            serverPath.append("https://");
//            serverPath.append(request.getServerName());
//        }else {
//            serverPath.append("http://");
//            serverPath.append(request.getServerName()).append(":").append("9001");
//        }
//        serverPath.append(request.getServerName()).append(":").append("8188");

        serverPath.append(env.getProperty("serverName"));
        serverPath.append(request.getContextPath());
        //文件保存的完整路径
        String path = env.getProperty("fileBaseStoreDIR") + "/" + backPath;

        //测试用
//        path = "D:/upload/tzapi" + "/" + backPath;

        MultipartFile file = file1[0];
        //获取文件名
        String fileName = file.getOriginalFilename();

        String fileType=file.getContentType();
        System.out.println("file.getContentType() = " + file.getContentType());
        String passType = env.getProperty("fileType");
        String[] split = passType.split(",");
        List<String> strings = Arrays.asList(split);
        if(!strings.contains(this.getExtName(fileName,'.'))){
            return Result.error(ResultEnum.NOPASSTYPE);
        }
        //获取转换后的uuid文件名
        String uuidFileName = this.getUUIDFileName(fileName);
        //完善附件对象信息,如果需要设置
//        att.setCreateTime(System.currentTimeMillis());
//        att.setSize(file.getSize());
//        att.setName(uuidFileName);
//        att.setExt(this.getExtName(fileName, '.'));
//        att.setRealPath(backPath + "/" + uuidFileName);

        File targetFile = new File(path);
        //创建文件夹
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        Map<String, Object> map = new HashMap<>();
        try {

            File targetFile2 = new File(path, uuidFileName);

            if (file instanceof QrCodeGenerate.MultipartFileDto){
                OutputStream out = new FileOutputStream(targetFile2);
                byte[] ss = file.getBytes();
                for(int i = 0; i < ss.length; i++) {
                    out.write(ss[i]);
                }
                out.flush();
                out.close();
            }else {
                file.transferTo(targetFile2);
            }

//            String s = Files.probeContentType(Paths.get(targetFile2.getPath()));
//            System.out.println("s = " + s);
            if(fileType.indexOf("image")>0) {
                long size = file.getSize();
                double scale = 1.0d;
                if (size >= 200 * 1024) {
                    scale = (200 * 1024f) / size;
                    if (scale < 0.1f) {
                        scale = scale * 10;
                    }
                }

                try {
                    //added by chenshun 2016-3-22 注释掉之前长宽的方式，改用大小
//            Thumbnails.of(filePathName).size(width, height).toFile(thumbnailFilePathName);
                    String thpath = env.getProperty("fileBaseStoreDIR") + "/thumb/" + backPath;
                    File thfile = new File(thpath);
                    //创建文件夹
                    if (!thfile.exists()) {
                        thfile.mkdirs();
                    }

                    String thumbnailFilePath = thpath + "/thum_" + uuidFileName;
                    if (size < 200 * 1024) {
                        Thumbnails.of(targetFile2).scale(1f).toFile(thumbnailFilePath);
                    } else {
                        Thumbnails.of(targetFile2).scale(scale).toFile(thumbnailFilePath);
                    }
                    map.put("thumbUrl", "thumb/" + backPath + "/thum_" + uuidFileName);

                } catch (Exception e1) {
                    map.put("thummsg", "图片压缩失败" + e1.getMessage());
                }
            }

            map.put("state", "SUCCESS");
            map.put("url", serverPath + env.getProperty("downloadApi") + uuidFileName + "&basepath=" + Base64Encode(backPath));
//            map.put("url", env.getProperty("downloadApi") + uuidFileName + "&basepath=" + Base64Encode(backPath));
            map.put("viewUrl", backPath + "/" + uuidFileName);
            map.put("title", this.getName(fileName,'.'));
            map.put("original", fileName);
            map.put("size", file.getSize());
            request.getParameterMap().keySet().forEach(d -> {
                if (!map.containsKey(d.toString())) {
                    map.put(d.toString(), request.getParameter(d.toString()));
                }
            });
            LOGGER.info("上传成功结束");
        } catch (Exception e) {
            LOGGER.info("upload error:", e);
            map.put("state", "上传失败");
        }
        return Result.success(map);

    }

    /**
     * @Description: 附件下载
     * @UpdateUser: 从未被修改
     * @UpdateDate: 从未被修改
     * @UpdateRemark:
     * @Version: 1.0
     * @Param: [response, name, basepath]
     * @return: void
     **/
    @CrossOrigin
    @RequestMapping("/download")
    public void download(HttpServletResponse response, String name, String basepath) throws IOException {
        if (StringUtils.hasText(name)) {
            response.reset();
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(name.getBytes("utf-8"), "iso-8859-1"));  //转码之后下载的文件名不会出现中文乱码
            response.setContentType("application/octet-stream;charset=UTF-8");
            //String backPath = this.getPath();
            //文件保存的完整路径
            String path = env.getProperty("fileBaseStoreDIR") + "/" + Base64Decode(basepath) + "/" + name;

            //测试用
//            path = "D:/upload/tzapi" + "/" + Base64Decode(basepath) + "/" + name;

            //读取文件
            InputStream in = new FileInputStream(path);
            OutputStream out = response.getOutputStream();
            //写文件
            int b;
            while ((b = in.read()) != -1) {
                out.write(b);
            }
            in.close();
            out.close();
        }
    }

    /**
     * Ueditor用uploadAtt接口
     * @param file1
     * @param request
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/uploadUeditorAtt", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
    public Object uploadUeditorFile(@RequestParam(value = "file", required = false) MultipartFile[] file1,
                                 HttpServletRequest request) {
        Result result = new Result();
        try {
           result = uploadhostFile(file1, request);
        } catch (Exception e) {
            LOGGER.info("upload error:", e);
        }
        return result.getData();

    }

    /**
     * @Description: getUUIDFileName:把文件名转换成uuid表示，防止文件名上传重复
     * @UpdateUser: 从未被修改
     * @UpdateDate: 从未被修改
     * @UpdateRemark:
     * @Version: 1.0
     * @Param: [fileName]
     * @return: java.lang.String
     **/
    private String getUUIDFileName(String fileName) {
//        UUID uuid = UUID.randomUUID();
        StringBuilder sb = new StringBuilder(100);

//        sb.append(uuid.toString()).append(".").append(this.getExtName(fileName, '.'));
        sb.append(this.getName(fileName,'.')).append(System.currentTimeMillis()).append(".").append(this.getExtName(fileName, '.'));
        return sb.toString();
    }

    /**
     * @Description: getExtName:获取文件后缀名
     * @UpdateUser: 从未被修改
     * @UpdateDate: 从未被修改
     * @UpdateRemark:
     * @Version: 1.0
     * @Param: [s, split]
     * @return: java.lang.String
     **/
    private String getExtName(String s, char split) {
        int i = s.lastIndexOf(split);
        int leg = s.length();
        return i > 0 ? (i + 1) == leg ? " " : s.substring(i + 1, s.length()) : " ";
    }

    /**
     * @Description: getExtName:获取文件后缀名
     * @UpdateUser: 从未被修改
     * @UpdateDate: 从未被修改
     * @UpdateRemark:
     * @Version: 1.0
     * @Param: [s, split]
     * @return: java.lang.String
     **/
    private String getName(String s, char split) {
        int i = s.lastIndexOf(split);
        int leg = s.length();
        return i > 0 ? (i + 1) == leg ? " " : s.substring(0,i) : " ";
    }
    /**
     * @Description: 根据年月日生成文件路径
     * @UpdateUser: 从未被修改
     * @UpdateDate: 从未被修改
     * @UpdateRemark:
     * @Version: 1.0
     * @Param: []
     * @return: java.lang.String
     **/
    private String getPath() {
        //获取年月日
        Calendar a = Calendar.getInstance();
        String year = String.valueOf(a.get(Calendar.YEAR));
        String month = String.valueOf(a.get(Calendar.MONTH) + 1);
        String day = String.valueOf(a.get(Calendar.DAY_OF_MONTH));
        StringBuilder backPath = new StringBuilder(128);
        backPath.append(year).append("/").append(month).append("/").append(day);
        return backPath.toString();
    }

    //上传图片
    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public Result upload(MultipartFile file, HttpServletRequest request) throws IOException {

        String backPath = this.getPath();
        //服务器地址
        StringBuilder serverPath = new StringBuilder();
        serverPath.append("http://");
        serverPath.append(request.getServerName()).append(":").append(request.getServerPort());
        serverPath.append(request.getContextPath());
        //文件保存的完整路径
        String path = env.getProperty("fileBaseStoreDIR") + "/" + backPath;
        String name = file.getOriginalFilename();
        name = name.substring(name.lastIndexOf("."));
        name = UUID.randomUUID().toString().replace("-", "") + name;

        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        file.transferTo(Paths.get(path, name));
        return Result.success(name);
    }
}
